// 定义文件上传任务类型
type UploadTask<R, K> = {
  myFlie: R;
  resolve: (res: K) => void;
  reject: (error: Error) => void;
};
type UploadFile<R = any, K = any> = (myFlie: R) => Promise<K>;

/**
 * 文件上传服务类（单例模式）,
 */
export class FileUploadService<R, K> {
  /** 当前上传的数量 */
  private currentUploads = 0;
  /** 一次最多上传多少个，剩下的加入队列 */
  private concurrency = 5;
  /** 上传队列 */
  private uploadTaskList: UploadTask<R, K>[] = [];
  /** 上传的方法 */
  private uploadFile: UploadFile<R, K>;

  /**
   * 私有构造函数
   */
  public constructor(_uploadFile: UploadFile, _concurrency?: number) {
    this.currentUploads = 0;
    this.concurrency = _concurrency || 5; // 默认并发数为2，可以根据需要调整
    this.uploadTaskList = [];
    this.uploadFile = _uploadFile;
  }

  /**
   * 执行文件上传
   * @param filesToUpload - 要上传的文件对象数组
   * @param concurrency - 并发上传数，默认为构造函数中设置的并发数
   */
  public upload(filesToUpload: R[], concurrency: number = this.concurrency): Promise<PromiseSettledResult<Awaited<K>>[]> {
    return new Promise<PromiseSettledResult<Awaited<K>>[]>((resolve, reject) => {
      const uploadPromises = filesToUpload.map((file) => this.addUploadTask(file));
      this.concurrency = concurrency; // 更新并发数

      // 返回所有上传任务的 Promise
      Promise.allSettled(uploadPromises)
        .then((res) => {
          resolve(res); // 所有任务完成后调用总体解决函数
        })
        .catch((err) => {
          console.error('文件上传过程中出现错误:');
          reject(err); // 如果有任务失败，直接调用总体拒绝函数
        });
    });
  }

  /**
   * 添加上传任务到队列
   * @param file - 要上传的文件对象
   */
  private addUploadTask(myFlie: R): Promise<K> {
    return new Promise<K>((resolve, reject) => {
      if (this.currentUploads < this.concurrency) {
        // 如果当前上传数小于并发数，则直接上传
        this.currentUploads++;
        this.uploadFile(myFlie)
          .then((res: K) => {
            this.currentUploads--;
            resolve(res);
            this.processQueue();
          })
          .catch((error) => {
            this.currentUploads--;
            console.error(`上传失败,文件：`, myFlie, '错误====', error);
            reject(error);
            this.processQueue();
          });
      } else {
        // 如果当前上传数达到并发数，则加入队列等待
        this.uploadTaskList.push({ myFlie, resolve, reject });
      }
    });
  }

  /**
   * 处理上传队列，依次执行上传任务
   */
  private processQueue(): void {
    if (this.uploadTaskList.length > 0) {
      const { myFlie, resolve, reject } = this.uploadTaskList.shift()!;
      this.addUploadTask(myFlie)
        .then((res: K) => {
          resolve(res); // 在完成上传后，调用任务的 resolve
        })
        .catch((err) => {
          reject(err);
        });
    }
  }

  /**
   * 停止上传
   */
  public abort(): void {
    this.uploadTaskList = [];
  }
}
